
DEBUG = True

from .xml import XML
from lxml import etree
from amplitude.dict import Dict
import amplitude
from .xslt_extensions import xslt_extensions

XSLNS = "http://www.w3.org/1999/XSL/Transform"
HTMLNS = "http://www.w3.org/1999/xhtml"

XSLT_TEMPLATE = """<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:html="http://www.w3.org/1999/xhtml"><xsl:output method="xml"/><xsl:template match="@*|node()"><xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy></xsl:template></xsl:stylesheet>"""

class XSLT(XML):
    """class for holding, manipulating, and using XSLT documents"""
	
    def __init__(self, xml, **args):
        XML.__init__(self, xml, **args)
        if etree.tostring(self.root) == '<xslt/>':
            self.root = etree.fromstring(XSLT_TEMPLATE)
        self.make_xslt()
        
    def append(self, s, *args):
        elem = XSLT.Element(s, *args)
        try:
            self.root.append(elem)
            self.make_xslt()
        except:
            self.root.remove(elem)
            raise

    def make_xslt(self):
        self.__xslt = etree.XSLT(self.root, extensions=xslt_extensions)
            
    def __call__(self, *args, **kwargs):
        return self.__xslt(*args, **kwargs)

    # == TEMPLATE METHODS == 
    
    @classmethod
    def Element(cls, s, *args):
        """given a template string s and string *args, return an Element. If s is already an Element, first convert to a string for template filling."""
        if type(s)==etree.Element:
            t = etree.tostring(s)
        else:
            t = s
        if len(args)==0:
            return etree.fromstring(t)
        elif len(args)==1 and type(args) in [dict, Dict]:
            return etree.fromstring(t % args[0])
        else:
            return etree.fromstring(t % tuple(args))
    
    @classmethod
    def stylesheet(cls, s):
        return """<?xml version="1.0"?>
    <xsl:stylesheet version="1.0" 
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:%s="%s"
            extension-element-prefixes="%s">
        %s
    </xsl:stylesheet>""" % (amplitude.NAMESPACE['prefix'], 
                            amplitude.NAMESPACE['url'],
                            amplitude.NAMESPACE['prefix'], 
                            s)

    @classmethod
    def copy_all(cls):
        return """<xsl:template match="@*|node()" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:copy xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
            <xsl:apply-templates select="@*|node()" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"/>
        </xsl:copy>
    </xsl:template>"""

    @classmethod
    def copy(cls, val):
        return """<xsl:copy xmlns:xsl="http://www.w3.org/1999/XSL/Transform">%s</xsl:copy>""" % val

    @classmethod
    def copy_select(cls, select, val):
        return """<xsl:copy select="%s" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">%s</xsl:copy>""" % (select, val,)

    @classmethod
    def copy_of(cls, select):
        return """<xsl:copy-of select="%s" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"/>""" % select

    @classmethod
    def choose(cls, test, when, otherwise=''):
        return """<xsl:choose xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:when test="%s" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
            %s
        </xsl:when>
        <xsl:otherwise xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
            %s
        </xsl:otherwise>
    </xsl:choose>""" % (test, when, otherwise,)

    @classmethod
    def template_match(cls, match, val):
        return """\n<xsl:template match="%s" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">%s</xsl:template>\n""" % (match, val,)

    @classmethod
    def template_match_mode(cls, match, mode, val):
        return """\n<xsl:template match="%s" mode="%s" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">%s</xsl:template>\n""" % (match, mode, val,)
                
    @classmethod
    def template_name(cls, name, val):
        return """<xsl:template name="%s" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">%s</xsl:template>""" % (name, val,)

    @classmethod
    def template_match_omission(cls, match):
        return """<xsl:template match="%s" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"/>""" % match

    @classmethod
    def apply_templates(cls):
        return """<xsl:apply-templates xmlns:xsl="http://www.w3.org/1999/XSL/Transform"/>"""

    @classmethod
    def apply_templates_mode(cls, mode):
        return """<xsl:apply-templates mode="%s" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"/>""" % mode

    @classmethod
    def apply_templates_select(cls, select):
        return """<xsl:apply-templates select="%s" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"/>""" % select

    @classmethod
    def apply_templates_select_mode(cls, select, mode):
        return """<xsl:apply-templates select="%s" mode="%s" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"/>""" % (select, mode,)

    @classmethod
    def element(cls, name, val):
        return """<xsl:element name="%s" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">%s</xsl:element>""" % (name, val,)
        
    @classmethod
    def attribute(cls, name, val):
        return """<xsl:attribute name="%s" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">%s</xsl:attribute>""" % (name, val)

    @classmethod
    def variable(cls, name, val):
        return """<xsl:variable name="%s" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">%s</xsl:variable>""" % (name, val)

    @classmethod
    def variable_select(cls, name, select):
        return """<xsl:variable name="%s" select="%s" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"/>""" % (name, select)

    @classmethod
    def value_of(cls, select):
        return """<xsl:value-of select="%s" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"/>""" % select

    @classmethod
    def text(cls, val):
        return """<xsl:text xmlns:xsl="http://www.w3.org/1999/XSL/Transform">%s</xsl:text>""" % val

    @classmethod
    def for_each(cls, select, val):
        return """<xsl:for-each select="%s" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">%s</xsl:for-each>""" % (select, val)

    @classmethod
    def if_test(cls, test, val):
        return """<xsl:if test="%s" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">%s</xsl:if>""" % (test, val)

    @classmethod
    def newline(cls,):
        return """<xsl:text xmlns:xsl="http://www.w3.org/1999/XSL/Transform">&#xa;</xsl:text>"""

    @classmethod
    def nbsp(cls,):
        return """<xsl:text xmlns:xsl="http://www.w3.org/1999/XSL/Transform">&#x00a0;</xsl:text>"""

    @classmethod
    def p(cls, val):
        return """<p>%s</p>""" % val

    @classmethod
    def p_class(cls, clas, val):
        return """<p class="%s">%s</p>""" % (clas, val)

    @classmethod
    def span_class(cls, clas, val):
        return """<span class="%s">%s</span>""" % (clas, val)

    @classmethod
    def output_method(cls, method):
        return """<xsl:output method="%s" encoding="utf-8" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"/>""" % method

    # Still to add: xsl:output, xsl:include, xsl:copy, xsl:copy-of, xsl:param, xsl:apply-templates select|match, xsl:call-template


